//二维模式限定范围
class CameraView2D {
    constructor(viewer, opts) {
        this.viewer = viewer;
        this.opts = opts || {};
        //显示限定范围的边界
        if (this.opts.limit && this.opts.limit.debugExtent) {
            this.debugExtent = this.opts.limit.debugExtent;
        }
        this.limitGlobe();
        // 绑定相机事件 
        this.viewer.camera.moveStart.addEventListener(this._cameraMoveStartHandler, this)
        this.viewer.camera.moveEnd.addEventListener(this._cameraMoveEndHandler, this)
    }

    //是否显示限定范围的边界
    get debugExtent() {
        return this.opts.limit && this.opts.limit.debugExtent;
    }
    set debugExtent(val) {
        if (!this.opts.limit) return;
        this.opts.limit.debugExtent = val;
        if (!this.debugExtentEntity) {
            var positions = []
            this.opts.limit.position.forEach(item => {
                positions.push(Cesium.Cartesian3.fromDegrees(item[0], item[1], 0))
            })
            let polyline = {
                id: 'drawPolyline',
                polyline: new Cesium.PolylineGraphics({
                    positions: positions,
                    show: true,
                    material: Cesium.Color.RED,
                    depthFailMaterial: new Cesium.PolylineOutlineMaterialProperty({ // 折线低于地形时用于绘制折线的材料
                        color: Cesium.Color.RED
                    }),
                    width: 2,
                    clampToGround: true,
                    eyeOffset: new Cesium.Cartesian3(0, 0, -100),
                    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
                })
            }
            this.debugExtentEntity = this.viewer.entities.add(polyline);
        }
        this.debugExtentEntity.show = val
    }

    //========== 方法 ========== 
    _cameraMoveStartHandler() {
    }
    _cameraMoveEndHandler() {
        this.limitGlobe();
    }
    //限定在指定范围球内
    limitGlobe() {
        if (!this.opts.limit) return;
        //当前屏幕 
        let position1 = new Cesium.Cartesian2(0, 0);
        let cartesian31 = zz3d.point.getCurrentMousePosition(this.viewer.scene, position1, false);

        let position2 = new Cesium.Cartesian2(this.viewer.canvas.width, 0);
        let cartesian32 = zz3d.point.getCurrentMousePosition(this.viewer.scene, position2, false);

        let position3 = new Cesium.Cartesian2(this.viewer.canvas.width, this.viewer.canvas.height);
        let cartesian33 = zz3d.point.getCurrentMousePosition(this.viewer.scene, position3, false);

        let position4 = new Cesium.Cartesian2(0, this.viewer.canvas.height);
        let cartesian34 = zz3d.point.getCurrentMousePosition(this.viewer.scene, position4, false);

        var rectangle = new Cesium.Rectangle.fromCartesianArray([cartesian31, cartesian32, cartesian33, cartesian34], Cesium.Ellipsoid.WGS84, new Cesium.Rectangle())

        //限制范围 
        var positions = this.opts.limit.position
        let cartographics = []
        positions.forEach(item => {
            cartographics.push(Cesium.Cartesian3.fromDegrees(item[0], item[1], 0))
        })
        let limitRectangle = new Cesium.Rectangle.fromCartesianArray(cartographics, Cesium.Ellipsoid.WGS84, new Cesium.Rectangle())
        //判断超出范围
        if (rectangle.west > limitRectangle.west && rectangle.south > limitRectangle.south && rectangle.north < limitRectangle.north && rectangle.east < limitRectangle.east) return;
        if (rectangle.west < limitRectangle.west && rectangle.south < limitRectangle.south && rectangle.north > limitRectangle.north && rectangle.east > limitRectangle.east) {
            let extent = {
                xMin: positions[0][0],
                yMin: positions[0][1],
                xMax: positions[2][0],
                yMax: positions[2][1],
            }
            this.viewer.zz.centerAtByBoundingSphere(extent);
            return;
        }
        // 左右都超出
        if (rectangle.west < limitRectangle.west && rectangle.east > limitRectangle.east) {
            let leftCenterPointx = (positions[0][0] + positions[3][0]) / 2;
            let leftCenterPointy = (positions[0][1] + positions[3][1]) / 2;
            let leftCenterPoint = [leftCenterPointx, leftCenterPointy]
            let rightCenterPointx = (positions[1][0] + positions[2][0]) / 2;
            let rightCenterPointy = (positions[1][1] + positions[2][1]) / 2;
            let rightCenterPoint = [rightCenterPointx, rightCenterPointy]
            let extent = {
                xMin: leftCenterPoint[0],
                yMin: leftCenterPoint[1],
                xMax: rightCenterPoint[0],
                yMax: rightCenterPoint[1],
            }
            this.viewer.zz.centerAtByBoundingSphere(extent);
            return;
        }
        // 上下都超出
        if (rectangle.north > limitRectangle.north && rectangle.south < limitRectangle.south) {
            let topCenterPointx = (positions[0][0] + positions[1][0]) / 2;
            let topCenterPointy = (positions[0][1] + positions[1][1]) / 2;
            let topCenterPoint = [topCenterPointx, topCenterPointy]
            let bottomCenterPointx = (positions[3][0] + positions[2][0]) / 2;
            let bottomCenterPointy = (positions[3][1] + positions[2][1]) / 2;
            let bottomCenterPoint = [bottomCenterPointx, bottomCenterPointy]
            let extent = {
                xMin: topCenterPoint[0],
                yMin: topCenterPoint[1],
                xMax: bottomCenterPoint[0],
                yMax: bottomCenterPoint[1],
            }
            this.viewer.zz.centerAtByBoundingSphere(extent);
            return;
        }
        //左西
        if (rectangle.west < limitRectangle.west) {
            let leftCenterPoint = new Cesium.Cartesian2(0, this.viewer.canvas.height / 2 + 10);
            let leftCenterCartesian3 = zz3d.point.getCurrentMousePosition(this.viewer.scene, leftCenterPoint, false);
            let left1 = Cesium.Cartesian3.fromDegrees(positions[0][0], positions[0][1], 0)
            let left2 = Cesium.Cartesian3.fromDegrees(positions[3][0], positions[3][1], 0)
            let exceedLeft = this.getDistanceByPointToLine_Coordinate(leftCenterCartesian3, left1, left2)
            if (exceedLeft > 0) {
                this.viewer.camera.moveRight(exceedLeft)
            }
        }
        //右东
        if (rectangle.east > limitRectangle.east) {
            let rightCenterPoint = new Cesium.Cartesian2(this.viewer.canvas.width, this.viewer.canvas.height / 2);
            let rightCenterCartesian3 = zz3d.point.getCurrentMousePosition(this.viewer.scene, rightCenterPoint, false);
            let right1 = Cesium.Cartesian3.fromDegrees(positions[1][0], positions[1][1], 0)
            let right2 = Cesium.Cartesian3.fromDegrees(positions[2][0], positions[2][1], 0)
            let exceedRight = this.getDistanceByPointToLine_Coordinate(rightCenterCartesian3, right1, right2)
            if (exceedRight > 0) {
                this.viewer.camera.moveLeft(exceedRight)
            }
        }
        //上北
        if (rectangle.north > limitRectangle.north) {
            let northCenterPoint = new Cesium.Cartesian2(this.viewer.canvas.width / 2, 0);
            let northCenterCartesian3 = zz3d.point.getCurrentMousePosition(this.viewer.scene, northCenterPoint, false);
            let north1 = Cesium.Cartesian3.fromDegrees(positions[0][0], positions[0][1], 0)
            let north2 = Cesium.Cartesian3.fromDegrees(positions[1][0], positions[1][1], 0)
            let exceedNorth = this.getDistanceByPointToLine_Coordinate(northCenterCartesian3, north1, north2)
            if (exceedNorth > 0) {
                this.viewer.camera.moveDown(exceedNorth)
            }
        }
        //下南
        if (rectangle.south < limitRectangle.south) {
            let southCenterPoint = new Cesium.Cartesian2(this.viewer.canvas.width / 2, this.viewer.canvas.height);
            let southCenterCartesian3 = zz3d.point.getCurrentMousePosition(this.viewer.scene, southCenterPoint, false);
            let south1 = Cesium.Cartesian3.fromDegrees(positions[2][0], positions[2][1], 0)
            let south2 = Cesium.Cartesian3.fromDegrees(positions[3][0], positions[3][1], 0)
            let exceedSouth = this.getDistanceByPointToLine_Coordinate(southCenterCartesian3, south1, south2)
            if (exceedSouth > 0) {
                this.viewer.camera.moveUp(exceedSouth)
            }
        }
    }

    /**
     * 点到线的距离
     */
    getDistanceByPointToLine_Coordinate(point, pnt1, pnt2) {
        var dis = 0;
        if (pnt1.x == pnt2.x) {
            if (pnt1.y == pnt2.y) {
                var dx = point.x - pnt1.x;
                var dy = point.y - pnt1.y;
                dis = Math.sqrt(dx * dx + dy * dy);
            } else
                dis = Math.abs(point.x - pnt1.x);
        } else {
            var lineK = (pnt2.y - pnt1.y) / (pnt2.x - pnt1.x);
            var lineC = (pnt2.x * pnt1.y - pnt1.x * pnt2.y) / (pnt2.x - pnt1.x);
            dis = Math.abs(lineK * point.x - point.y + lineC) / (Math.sqrt(lineK * lineK + 1));
        }
        return dis;
    }

    // 销毁
    destroy() {
        // 绑定相机事件
        this.viewer.camera.moveStart.removeEventListener(this._cameraMoveStartHandler, this)
        this.viewer.camera.removeEventListener(this._cameraMoveEndHandler, this)
        if (this.debugExtentEntity) {
            this.viewer.entities.remove(this.debugExtentEntity)
            delete this.debugExtentEntity
        }
    }
}